#pragma once 
#include<iostream>
#include<string.h>
#include<assert.h>
namespace imitate 
{
    class string 
    {
        friend std::ostream& operator<<(std::ostream& out,const string& d);
        friend std::istream& operator>>(std::istream& ion,const string& d);

    public: 
        typedef char* iterator;

        void swap(string& d)
        {
            std::swap(_str,d._str);
            std::swap(_size,d._size);
            std::swap(_capacity,d._capacity);
        }

        string(const char* str="")
        {
            _size=strlen(str);
            _capacity=_size;
            _str=new char[_capacity+1];
            strcpy(_str,str);
        }

        string(const string& d)
            :_str(nullptr)
        {
            string s(d._str);
            swap(s);
        }

        ~string()
        {
            delete[] _str;
            _str=nullptr;
            _size=_capacity=0;
        }

        string& operator=(string d)
        {
            swap(d);
            return *this;
        }

        char* c_str() const 
        {
            return _str;
        }

        char& operator[](size_t pos)
        {
            return _str[pos];
        }

        const char& operator[](size_t pos) const 
        {
            return _str[pos];
        }

        iterator begin() const 
        {
            return _str;
        }

        iterator end() const 
        {
            return _str+_size;
        }

        size_t size() const 
        {
            return _size;
        }

        size_t capacity() const 
        {
            return _capacity;
        }

        void reserve(size_t size)
        {
            if(size>_capacity)
            {
                char* tem=new char[size+1];
                strcpy(tem,_str);
                delete[] _str;
                _str=tem;
                _capacity=size; 
            }
        }

        void resize(size_t size)
        {
            if(size>_size && size>_capacity)
            {
                char* tem=new char[size+1];
                strcpy(tem,_str);
                delete[] _str;
                _str=tem;
                _size=size;
                _capacity=size;
            }
            else if(size>_size && size<=_capacity)
                _size=size;
        }

        bool operator>(const string& d) const 
        {
            size_t i=0;
            if(_str[0]>d._str[0])
                return true;
            if(_str[0]<d._str[0])
                return false;
            if(_str[0]==d._str[0])
            {
                while(i<_size&&i<d._size)
                {
                    if(_str[i]==d._str[i])
                        i++;
                    else if(_str[i]>d._str[i])
                        return true;
                    else 
                        return false;
                }
                if(i==_size&&i==d._size)
                    return false;
                if(i>_size&&i==d._size)
                    return false;
                if(i<_size&&i==d._size)
                    return true;
            }
        }
        
        bool operator==(const string& d) const 
        {
            return strcmp(_str,d._str)==0;
        }

        bool operator>=(const string& d) const 
        {
            return (*this>d)||(*this==d);
        }

        bool operator<(const string& d) const 
        {
            return !(*this>=d);
        }

        bool operator<=(const string& d) const 
        {
            return !(*this>d);
        }
        
        void push_back(char ch)
        {
            if(_capacity==0)
            {  
                reserve(15);
            }
            else if(_size==_capacity)
            {
                reserve(2*_capacity);
            }
            _str[_size++]=ch;
            _str[_size]='\0';
        }

        void apptend(const char* str)
        {
            
        }
    private:
        char* _str;
        size_t _size;
        size_t _capacity;
        static size_t nops;
    };
    size_t imitate::string::nops=-1;
    std::ostream& operator<<(std::ostream& out,const string& d)
    {
       out<<d._str;
       return out;
    }
    std::istream& operator>>(std::istream& ion,const string& d)
    {
        ion>>d._str;
        return ion;
    }
}



